﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using PowerManager.Entities;

namespace PowerManager
{
    public static class CmdHandler
    {
        public delegate void ErrorThrowedEventHandler(string data, string command);
        public static ErrorThrowedEventHandler ErrorThrowed;

        public static void StartWinSettings()
        {
            var p = new Process();
            try
            {
                p.SetParams(Properties.Settings.Default.CmdExplorerPath,
                    Properties.Settings.Default.CmdPowersupplyPath);
                p.Start();
                var resErrorOut = p.StandardError.ReadToEnd();
                if (!string.IsNullOrEmpty(resErrorOut))
                    throw new AccessViolationException(string.Format(Properties.Resources.ExceptionFormat,
                        Properties.Settings.Default.mCommand, resErrorOut));
            }
            catch (Exception ex)
            {
                if (ErrorThrowed != null)
                    ErrorThrowed(ex.Message, 
                        string.Format("{0} {1}", 
                        p.StartInfo.FileName,
                        p.StartInfo.Arguments));
            }
        }

        public static CurrentSchemes GetPowerSchemes()
        {
            var schemes = new CurrentSchemes();
            var p = new Process();
            try
            {
                p.SetParams(Properties.Settings.Default.mCommand, Properties.Settings.Default.CmdGetListSchemes);
                p.Start();
                var resErrorOut = p.StandardError.ReadToEnd();
                if (!string.IsNullOrEmpty(resErrorOut))
                    throw new AccessViolationException(string.Format(Properties.Resources.ExceptionFormat,
                        Properties.Settings.Default.mCommand, resErrorOut));
                schemes = p.StandardOutput.ReadToEnd().DataToList().ListToSchemes();
                schemes.ActiveScheme = GetActiveScheme();
            }
            catch (AccessViolationException ex)
            {
                MessageBox.Show(string.Format("{0}\r\n{1}", Properties.Resources.ExceptionMsg, ex.Message),
                    Properties.Resources.SetErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Stop);
            }
            catch (Exception ex)
            {
                if (ErrorThrowed != null)
                    ErrorThrowed(ex.Message, 
                        string.Format("{0} {1}", 
                        Properties.Settings.Default.mCommand,
                        p.StartInfo.Arguments));
            }

            return schemes;
        }

        public static Scheme GetActiveScheme()
        {
            var resScheme = new Scheme { Name = Properties.Resources.CurrentSchemeError };
            var p = new Process();
            try
            {
                p.SetParams(Properties.Settings.Default.mCommand, Properties.Settings.Default.CmdGetActiveScheme);
                p.Start();
                var resErrorOut = p.StandardError.ReadToEnd();
                if (!string.IsNullOrEmpty(resErrorOut))
                    throw new AccessViolationException(string.Format(Properties.Resources.ExceptionFormat, Properties.Settings.Default.mCommand, resErrorOut));
                var resOutput = p.StandardOutput.ReadToEnd().DataToList();
                var schemes = resOutput.ListToSchemes();
                resScheme = schemes.AllSchemes[0];
            }
            catch (AccessViolationException ex)
            {
                MessageBox.Show(string.Format("{0}\r\n{1}", Properties.Resources.ExceptionMsg, ex.Message),
                    Properties.Resources.SetErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Stop);
            }
            catch (Exception ex)
            {
                if (ErrorThrowed != null)
                    ErrorThrowed(ex.Message,
                        string.Format("{0} {1}",
                        Properties.Settings.Default.mCommand,
                        p.StartInfo.Arguments));
            }

            return resScheme;
        }

        public static List<string> SetPowerScheme(string guid)
        {
            if (string.IsNullOrEmpty(guid))
                return new List<string> { Properties.Resources.GuidEmpty };

            var p = new Process();
            try
            {
                p.SetParams(Properties.Settings.Default.mCommand, string.Format(Properties.Settings.Default.CmdSetPowerScheme, guid));
                p.Start();
                var res = p.StandardError.ReadToEnd();
                if (!string.IsNullOrEmpty(res))
                    throw new Exception(string.Format(Properties.Resources.ExceptionFormat,
                        Properties.Settings.Default.mCommand, p.StartInfo.Arguments, res));
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0}\r\n{1}", Properties.Resources.SetErrorMsg, ex.Message),
                    Properties.Resources.SetErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Stop);
            }

            return p.StandardOutput.ReadToEnd().DataToList()
                ?? new List<string> { Properties.Resources.ProcessParseFailed };
        }
    }

    public static class Ex
    {
        public static List<string> DataToList(this string value)
        {
            value = value.Trim().Trim('\r', '\n').Replace("\r\n", "°");
            var list = value.Split('°').ToList();
            return list;
        }

        public static CurrentSchemes ListToSchemes(this List<string> value)
        {
            var res = new CurrentSchemes { AllSchemes = new List<Scheme>() };

            foreach (var val in value)
            {
                var resScheme = val.ToScheme();
                if (resScheme != null)
                    res.AllSchemes.Add(resScheme);
            }
            if (res.AllSchemes.Count < 1)
                res.AllSchemes.Add(new Scheme { Name = Properties.Resources.ProcessParseFailed });
            return res;
        }

        public static Scheme ToScheme(this string data)
        {
            string guid = string.Empty, name = string.Empty;
            {
                var reges = new Regex(@"\S{8}-\S{4}-\S{4}-\S{4}-\S{12}", RegexOptions.IgnoreCase);
                var match = reges.Match(data);
                if (match.Success)
                    guid = match.Value;
            }
            {
                var reges = new Regex(@"\((.*)\)");
                var match = reges.Match(data);
                if (match.Success)
                    name = match.Value.Trim('(', ')');
            }
            return string.IsNullOrEmpty(guid) ? null : new Scheme { Guid = guid, Name = name, };
        }

        public static Process SetParams(this Process p, string mCommand, string args)
        {
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.FileName = mCommand;
            p.StartInfo.Arguments = args;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.StandardOutputEncoding = Encoding.GetEncoding(866);
            p.StartInfo.StandardErrorEncoding = Encoding.GetEncoding(866);
            p.EnableRaisingEvents = true;
            return p;
        }
    }
}
